/*
 *  Copyright (C) 2010 Jesus Navalon i Pastor <jnavalon at redhermes dot net>
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * pn_Main.java
 *
 * Created on 06/08/2010, 20:07:13
 */
package kuasar.plugin.vmcreator.gui;

import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
import java.util.TreeMap;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import kuasar.plugin.Intercom.GUI;
import kuasar.plugin.Intercom.ODR;
import kuasar.plugin.vmcreator.Config;
import kuasar.plugin.utils.XML;
import kuasar.plugin.vmcreator.Config.VMList;
import kuasar.plugin.vmcreator.gui.Favorites.pn_Favorites;
import kuasar.plugin.vmcreator.gui.tooltasks.AddHost.pn_Properties;
import kuasar.plugin.vmcreator.gui.tooltasks.AddHost.pn_TB_AddHost;
import kuasar.plugin.vmcreator.utils.Others;
import org.jdom.Element;

/**
 *
 * @author Jesus Navalon i Pastor <jnavalon at redhermes dot net>
 */
public final class pn_Main extends kuasar.plugin.classMod.AbstractPanel {

    public String onAir = "/";
    protected Stack<String> back = new Stack<String>();
    protected Stack<String> next = new Stack<String>();
    public pn_ToolBar tb = null;
    private pn_Favorites favorites = null;
    /** Creates new form pn_Main */
    public pn_Main() {
        checkPaths();
        initComponents();
        pn_aux.setVisible(false);
        scp_List.getViewport().setOpaque(false);
        lst_Nets.setBorder(BorderFactory.createEmptyBorder());
        fillList("/", false);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        scp_List = new javax.swing.JScrollPane();
        lst_Nets = new kuasar.plugin.vmcreator.classMod.JListView();
        lbl_Info = new javax.swing.JLabel();
        pn_aux = new javax.swing.JPanel();

        setOpaque(false);

        scp_List.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
        scp_List.setViewportBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));

        lst_Nets.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
        lst_Nets.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        lst_Nets.setDoubleBuffered(true);
        lst_Nets.setOpaque(false);
        lst_Nets.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                lst_NetsMouseClicked(evt);
            }
        });
        lst_Nets.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseMoved(java.awt.event.MouseEvent evt) {
                lst_NetsMouseMoved(evt);
            }
        });
        lst_Nets.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                lst_NetsKeyReleased(evt);
            }
        });
        scp_List.setViewportView(lst_Nets);

        lbl_Info.setForeground(new java.awt.Color(204, 204, 204));

        pn_aux.setOpaque(false);
        pn_aux.addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentResized(java.awt.event.ComponentEvent evt) {
                pn_auxComponentResized(evt);
            }
        });

        javax.swing.GroupLayout pn_auxLayout = new javax.swing.GroupLayout(pn_aux);
        pn_aux.setLayout(pn_auxLayout);
        pn_auxLayout.setHorizontalGroup(
            pn_auxLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 185, Short.MAX_VALUE)
        );
        pn_auxLayout.setVerticalGroup(
            pn_auxLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 302, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(24, 24, 24)
                .addComponent(lbl_Info, javax.swing.GroupLayout.DEFAULT_SIZE, 445, Short.MAX_VALUE)
                .addGap(25, 25, 25))
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(scp_List, javax.swing.GroupLayout.DEFAULT_SIZE, 291, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(pn_aux, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(pn_aux, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(scp_List, javax.swing.GroupLayout.DEFAULT_SIZE, 302, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(lbl_Info))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void lst_NetsKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_lst_NetsKeyReleased
        Element root = XML.getElementOnPath("/", (Element) ODR.getValue(Config.path + "." + Config.network));
        if (evt.getKeyCode() == KeyEvent.VK_DELETE) {
            for (int i = 0; i < lst_Nets.getSelectedIndices().length; i++) {
                Object[] values = (Object[]) lst_Nets.getSelectedValues()[lst_Nets.getSelectedValues().length - i - 1];
                if(values[3] == null)
                    Others.removeVMFile(XML.getElementOnPath(onAir, root));
                else
                    Others.removeVMFile((String) values[3]);
                XML.RemoveElement(onAir, root, (String) values[2]);
            }
            if (XML.Save(Config.path, Config.network, root)) {
                kuasar.plugin.Intercom.GUI.launchInfo("Item(s) deleted successfully!");
            }
            fillList(onAir, false);
        }
    }//GEN-LAST:event_lst_NetsKeyReleased

    private void lst_NetsMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lst_NetsMouseClicked

        if (!evt.isShiftDown() && !evt.isControlDown()) {
            Object[] cell = (Object[]) lst_Nets.getSelectedValue();
            if(cell == null) return;
            if (cell[3] == null) {
                groupClicked((String) cell[2]);
            } else {
                vmClicked((String) cell[3]);
            }
        }

    }//GEN-LAST:event_lst_NetsMouseClicked

    private void lst_NetsMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lst_NetsMouseMoved
        if (evt.isControlDown()) {
            lst_Nets.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        } else {
            lst_Nets.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        }
    }//GEN-LAST:event_lst_NetsMouseMoved

    private void pn_auxComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_pn_auxComponentResized
        pn_aux.getComponent(0).setBounds(0,0,pn_aux.getWidth(),pn_aux.getHeight());
    }//GEN-LAST:event_pn_auxComponentResized

    public void reloadList(){
        fillList(onAir, false);
    }

    public void reloadFavorites(){
        if(favorites != null)
            favorites.reload();
    }

    protected void showFavorites(){
        pn_aux.setVisible(true);
        favorites = new pn_Favorites(this);
        pn_aux.removeAll();
        pn_aux.add(favorites);
    }
    protected void hideFavorites(){
        pn_aux.setVisible(false);
        favorites=null;
    }
    private HashMap<String,Object> loadMapVM(String filename){
        String path = ((String) kuasar.plugin.Intercom.ODR.getValue("$PLUGINDIR")) + File.separator + kuasar.plugin.vmcreator.Config.path + File.separator + kuasar.plugin.vmcreator.Config.virtualmachine + File.separator + filename;
        HashMap<String, Object> map = null;
        try{
            FileInputStream fis = new FileInputStream(path);
            ObjectInputStream ois = new ObjectInputStream(fis);
            map = (HashMap<String,Object>) ois.readObject();
            ois.close();
            fis.close();
        }catch(IOException e){
            System.err.println("Data hasn't been loaded! \nCause: " + e.getMessage());
        }catch(ClassNotFoundException e){
            System.err.println("Data is corrupted or File hasn't a correct format! Cause: " + e.getMessage());
        }
        return map;
    }

    protected void editVM(){
        Object[] data = (Object[]) lst_Nets.getSelectedValue();
        HashMap<String,Object> map = null;
        if(data[VMList.PATHMAP] != null){
            map = loadMapVM((String) data[VMList.PATHMAP]);
        }
        if(map==null)return;

        GUI.loadToolBar(new pn_TB_AddHost(this, map,(String) data[VMList.NAME],(String) data[VMList.PATHMAP]));
    }

    public void restoreList(){
       scp_List.removeAll();
       lst_Nets.setBounds(scp_List.getBounds());
       scp_List.add(lst_Nets, null);
       scp_List.updateUI();
       tb.deactivateDialog();
    }

    private void vmClicked(String filename){
        HashMap<String,Object> map=null;
        map = loadMapVM(filename);
        if(map==null) return;
        scp_List.removeAll();
        pn_Properties prop = new pn_Properties(this,map);
        prop.setBounds(scp_List.getBounds());
        scp_List.add(prop, null);
        scp_List.updateUI();
        tb.activateDialog();
    }

    private void checkPaths() {
        String path = ((String) kuasar.plugin.Intercom.ODR.getValue("$PLUGINDIR")) + File.separator + kuasar.plugin.vmcreator.Config.path + File.separator + kuasar.plugin.vmcreator.Config.favorites;
        File file = new File(path);
        if (!file.exists()) {
            if (!file.mkdirs()) {
                System.err.println("Error: Favorites VM won't be saved! I couldn't make" + kuasar.plugin.vmcreator.Config.favorites + "directory");
            }
        }
        path = ((String) kuasar.plugin.Intercom.ODR.getValue("$PLUGINDIR")) + File.separator + kuasar.plugin.vmcreator.Config.path + File.separator + kuasar.plugin.vmcreator.Config.virtualmachine;
        file = new File(path);
        if (!file.exists()) {
            if (!file.mkdirs()) {
                System.err.println("Error: VM Nodes won't be saved! I couldn't make " + kuasar.plugin.vmcreator.Config.virtualmachine + " directory");
            }
        }
    }

    public boolean fillList(String netpath, boolean saveAddr) {
        lbl_Info.setText("");
        try {

            Element root = XML.getElementOnPath(netpath, (Element) ODR.getValue(Config.path + "." + Config.network));
            TreeMap<String, Object[]> tm = new TreeMap<String, Object[]>();
            List ellist = root.getChildren();

            if (ellist == null) {
                return false;
            }

            DefaultListModel model = new DefaultListModel();
            lst_Nets.setModel(model);

            for (int i = 0; i < ellist.size(); i++) {
                Element lastelem = (Element) ellist.get(i);
                Object[] cell = new Object[5];
                if (lastelem.getAttributeValue("type").trim().length() == 0) {
                    cell[VMList.ICON] = new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/icon"));
                } else {
                    cell[VMList.ICON] = new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/netlist/" + lastelem.getAttributeValue("icon").trim()));
                    cell[VMList.PATHMAP] = lastelem.getAttributeValue("path");
                }

                cell[VMList.NAME] = lastelem.getAttributeValue("name");
                cell[VMList.XMLNAME] = lastelem.getName();
                cell[VMList.LABEL] = lbl_Info;
                tm.put(lastelem.getName(), cell);
            }

            Iterator it = tm.keySet().iterator();
            while (it.hasNext()) {
                model.addElement(tm.get((String) it.next()));
            }

            if (!saveAddr) {
                return true;
            }
            if (netpath.length() > 0) {
                back.push(onAir);
                onAir = netpath;
            }

            try {
                if (onAir.equals(next.peek())) {
                    next.pop();
                } else {
                    next.clear();
                }
            } catch (EmptyStackException es) {
            }

            if (tb != null) {
                tb.checkAddrAcc();
            }
            return true;
        } catch (Exception ex) {
            System.err.println("I can't read a correct  XML estructure");
            return false;
        }

    }

    private void groupClicked(String data) {
        if (onAir.endsWith("/")) {
            fillList(onAir + data, true);
        } else {
            fillList(onAir + "/" + data, true);
        }
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    public javax.swing.JLabel lbl_Info;
    private javax.swing.JList lst_Nets;
    private javax.swing.JPanel pn_aux;
    private javax.swing.JScrollPane scp_List;
    // End of variables declaration//GEN-END:variables
}
